home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
HPAVC
/
HPAVC CD-ROM.iso
/
WD_SRC.ZIP
/
SYSTEM
/
SCREEN.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1995-01-30
|
17KB
|
849 lines
#include "..\Source\LastWolf.hpp"
// Stuff for text display.
char *rom_char_set = (char *)0xF0000; // rom characters 8x8
#define CHAR_HEIGHT 8
#define CHAR_WIDTH 8
#define VGA_MEM 0xA0000;
char oldScreenMode;
BYTE palette[768];
BOOL bScreenInitted=FALSE;
short xPages, xPlanes; // Used for mode X only
short iWidthBytes;
short curDispPage=0;
#ifdef MODE_X
long MakeModeXDWord( void * );
#pragma aux MakeModeXDWord = \
"mov al,[ebx+12]" \
"mov ah,[ebx+8]" \
"bswap eax" \
"mov ah,[ebx+4]" \
"mov al,[ebx]" \
value [eax] \
parm [ebx];
//4 planes
//1 page
Register Mode360x480[] =
{
{ 0x3c2, 0x0, 0xe7},
{ 0x3d4, 0x0, 0x6b},
{ 0x3d4, 0x1, 0x59},
{ 0x3d4, 0x2, 0x5a},
{ 0x3d4, 0x3, 0x8e},
{ 0x3d4, 0x4, 0x5e},
{ 0x3d4, 0x5, 0x8a},
{ 0x3d4, 0x6, 0x0d},
{ 0x3d4, 0x7, 0x3e},
{ 0x3d4, 0x8, 0x0},
{ 0x3d4, 0x9, 0x40},
{ 0x3d4, 0x10, 0xea},
{ 0x3d4, 0x11, 0xac},
{ 0x3d4, 0x12, 0xdf},
{ 0x3d4, 0x13, 0x2d},
{ 0x3d4, 0x14, 0x0},
{ 0x3d4, 0x15, 0xe7},
{ 0x3d4, 0x16, 0x06},
{ 0x3d4, 0x17, 0xe3},
{ 0x3c4, 0x1, 0x01},
{ 0x3c4, 0x4, 0x06},
{ 0x3ce, 0x5, 0x40},
{ 0x3ce, 0x6, 0x05},
{ 0x3c0, 0x10, 0x41},
{ 0x3c0, 0x13, 0x00},
};
//4 planes
//2 pages
Register Mode360x360[] =
{
{ 0x3c2, 0x0, 0x67},
{ 0x3d4, 0x0, 0x6b},
{ 0x3d4, 0x1, 0x59},
{ 0x3d4, 0x2, 0x5a},
{ 0x3d4, 0x3, 0x8e},
{ 0x3d4, 0x4, 0x5e},
{ 0x3d4, 0x5, 0x8a},
{ 0x3d4, 0x6, 0xbf},
{ 0x3d4, 0x7, 0x1f},
{ 0x3d4, 0x8, 0x0},
{ 0x3d4, 0x9, 0x40},
{ 0x3d4, 0x10, 0x88},
{ 0x3d4, 0x11, 0x85},
{ 0x3d4, 0x12, 0x67},
{ 0x3d4, 0x13, 0x2d},
{ 0x3d4, 0x14, 0x0},
{ 0x3d4, 0x15, 0x6d},
{ 0x3d4, 0x16, 0xba},
{ 0x3d4, 0x17, 0xe3},
{ 0x3c4, 0x1, 0x01},
{ 0x3c4, 0x4, 0x06},
{ 0x3ce, 0x5, 0x40},
{ 0x3ce, 0x6, 0x05},
{ 0x3c0, 0x10, 0x41},
{ 0x3c0, 0x13, 0x00},
};
Register Mode400x600[] =
{
{ 0x3c2, 0x0, 0xe7},
{ 0x3d4, 0x0, 0x70},
{ 0x3d4, 0x1, 0x63},
{ 0x3d4, 0x2, 0x64},
{ 0x3d4, 0x3, 0x92},
{ 0x3d4, 0x4, 0x65},
{ 0x3d4, 0x5, 0x82},
{ 0x3d4, 0x6, 0x70},
{ 0x3d4, 0x7, 0xf0},
{ 0x3d4, 0x8, 0x0},
{ 0x3d4, 0x9, 0x60},
{ 0x3d4, 0x10, 0x5b},
{ 0x3d4, 0x11, 0x8c},
{ 0x3d4, 0x12, 0x57},
{ 0x3d4, 0x13, 0x32},
{ 0x3d4, 0x14, 0x0},
{ 0x3d4, 0x15, 0x58},
{ 0x3d4, 0x16, 0x70},
{ 0x3d4, 0x17, 0xe3},
{ 0x3c4, 0x1, 0x01},
{ 0x3c4, 0x4, 0x06},
{ 0x3ce, 0x5, 0x40},
{ 0x3ce, 0x6, 0x05},
{ 0x3c0, 0x10, 0x41},
{ 0x3c0, 0x13, 0x00},
};
Register Mode320x240[] =
{
{ 0x3c2, 0x0, 0xe3},
{ 0x3d4, 0x0, 0x5f},
{ 0x3d4, 0x1, 0x4f},
{ 0x3d4, 0x2, 0x50},
{ 0x3d4, 0x3, 0x82},
{ 0x3d4, 0x4, 0x54},
{ 0x3d4, 0x5, 0x80},
{ 0x3d4, 0x6, 0xd},
{ 0x3d4, 0x7, 0x3e},
{ 0x3d4, 0x8, 0x0},
{ 0x3d4, 0x9, 0x41},
{ 0x3d4, 0x10, 0xea},
{ 0x3d4, 0x11, 0xac},
{ 0x3d4, 0x12, 0xdf},
{ 0x3d4, 0x13, 0x28},
{ 0x3d4, 0x14, 0x0},
{ 0x3d4, 0x15, 0xe7},
{ 0x3d4, 0x16, 0x6},
{ 0x3d4, 0x17, 0xe3},
{ 0x3c4, 0x1, 0x1},
{ 0x3c4, 0x4, 0x6},
{ 0x3ce, 0x5, 0x40},
{ 0x3ce, 0x6, 0x5},
{ 0x3c0, 0x10, 0x41},
{ 0x3c0, 0x13, 0x0},
};
Register Mode320x200[] =
{
{ 0x3c2, 0x0, 0x63},
{ 0x3d4, 0x0, 0x5f},
{ 0x3d4, 0x1, 0x4f},
{ 0x3d4, 0x2, 0x50},
{ 0x3d4, 0x3, 0x82},
{ 0x3d4, 0x4, 0x54},
{ 0x3d4, 0x5, 0x80},
{ 0x3d4, 0x6, 0xbf},
{ 0x3d4, 0x7, 0x1f},
{ 0x3d4, 0x8, 0x0},
{ 0x3d4, 0x9, 0x41},
{ 0x3d4, 0x10, 0x9c},
{ 0x3d4, 0x11, 0x8e},
{ 0x3d4, 0x12, 0x8f},
{ 0x3d4, 0x13, 0x28},
{ 0x3d4, 0x14, 0x0},
{ 0x3d4, 0x15, 0x96},
{ 0x3d4, 0x16, 0xb9},
{ 0x3d4, 0x17, 0xe3},
{ 0x3c4, 0x1, 0x01},
{ 0x3c4, 0x4, 0x06},
{ 0x3ce, 0x5, 0x40},
{ 0x3ce, 0x6, 0x05},
{ 0x3c0, 0x10, 0x41},
{ 0x3c0, 0x13, 0x0},
};
/* Code from TWEAK */
/*
readyVgaRegs() does the initialization to make the VGA ready to
accept any combination of configuration register settings.
This involves enabling writes to index 0 to 7 of the CRT controller
(port 0x3d4), by clearing the most significant bit (bit 7) of index
0x11.
*/
void readyVgaRegs(void)
{
int v;
outp(0x3d4,0x11);
v = inp(0x3d5) & 0x7f;
outp(0x3d4,0x11);
outp(0x3d5,v);
}
/*
outReg sets a single register according to the contents of the
passed Register structure.
*/
void outReg(Register r)
{
switch (r.port)
{
/* First handle special cases: */
case ATTRCON_ADDR:
inp(STATUS_ADDR); /* reset read/write flip-flop */
outp(ATTRCON_ADDR, r.index | 0x20);
/* ensure VGA output is enabled */
outp(ATTRCON_ADDR, r.value);
break;
case MISC_ADDR:
case VGAENABLE_ADDR:
outp(r.port, r.value); /* directly to the port */
break;
case SEQ_ADDR:
case GRACON_ADDR:
case CRTC_ADDR:
default: /* This is the default method: */
outp(r.port, r.index); /* index to port */
outp(r.port+1, r.value);/* value to port+1 */
break;
}
}
/*
outRegArray sets n registers according to the array pointed to by r.
First, indexes 0-7 of the CRT controller are enabled for writing.
*/
void outRegArray(Register *r, int n)
{
readyVgaRegs();
while (n--)
outReg(*r++);
}
BOOL s_SetVideoMode( WORD newVidMode )
{
DWORD x;
/* Set variables related to screen access */
switch( newVidMode )
{
case 0:
xPlanes=4;
xPages=4;
s_Width = 320;
s_Height = 200;
break;
case 1:
xPlanes=4;
xPages=4;
s_Width = 320;
s_Height = 240;
break;
case 2:
xPlanes=4;
xPages=2;
s_Width = 360;
s_Height = 360;
break;
case 3:
xPlanes=4;
xPages=1;
s_Width=360;
s_Height=480;
break;
case 4:
xPlanes=4;
xPages=1;
s_Width=400;
s_Height=600;
break;
default:
xPlanes=4;
xPages=4;
s_Width = 320;
s_Height = 200;
}
s_SizeBytes = s_Width * s_Height;
iWidthBytes = s_Width/xPlanes;
#ifdef DOS
/* Set VGA BIOS mode 13h: */
s_SetMode(0x13);
// Have TWEAK's stuff do the real work
if( newVidMode == 0 )
outRegArray( Mode320x200, sizeof(Mode320x200)/sizeof(Register));
else if( newVidMode == 1 )
outRegArray( Mode320x240, sizeof(Mode320x240)/sizeof(Register));
else if( newVidMode == 2 )
outRegArray( Mode360x360, sizeof(Mode360x360)/sizeof(Register));
else if( newVidMode == 3 )
outRegArray( Mode360x480, sizeof(Mode360x480)/sizeof(Register));
else if( newVidMode == 4 )
outRegArray( Mode400x600, sizeof(Mode400x600)/sizeof(Register));
else
outRegArray( Mode320x200, sizeof(Mode320x200)/sizeof(Register));
// Set our display page to 0
outp( CRTC_ADDR, 0x0C );
outp( CRTC_ADDR+1, 0 );
outp( CRTC_ADDR, 0x0D );
outp( CRTC_ADDR+1, 0 );
#endif
// Create the x lookup information.
s_PagedWidth = iWidthBytes;
s_PageLookup = new DWORD[s_Width];
for( x=0; x < s_Width; x++ )
s_PageLookup[x] = ((x % xPlanes) * (s_SizeBytes/xPlanes)) + (x/xPlanes);
return TRUE;
}
BOOL s_Init()
{
/* Init stuff */
#ifdef DOS
oldScreenMode = s_GetMode();
#endif
s_SetVideoMode( videoMode );
pVgaMem = (char *)VGA_MEM;
pScreenMem = (char *)malloc( s_SizeBytes );
bScreenInitted = TRUE;
#ifdef PALETTE_MAPS
/* Load the palette maps and set the palette */
if( s_SetPaletteMaps() == FALSE )
return FALSE;
#endif
return TRUE;
}
BOOL s_DrawRegion( DWORD x1, DWORD y1, DWORD x2, DWORD y2, DWORD destX, DWORD destY )
{
DWORD plane;
DWORD actStart=0, visStart;
DWORD blitSize, destBlitPos, srcBlitPos;
DWORD y;
// Get our drawing page right.
if( xPages > 1 )
{
if( curDispPage == 0 )
actStart = 1 * iWidthBytes * s_Height;
else
actStart = 0;
}
// Get the blit size for a horizontal line.
blitSize = (x2-x1);
blitSize = ((blitSize / xPlanes) / 4)+1;
for( plane=0; plane < xPlanes; plane++ )
{
outpw( SEQ_ADDR, ( (0x01 << plane << 8)) + 0x02 );
destBlitPos = actStart + (iWidthBytes*destY) + (destX/4);
//srcBlitPos = (plane * (s_SizeBytes/xPlanes)) + (y1 * s_PagedWidth) + x1;
srcBlitPos = s_PageLookup[x1+plane] + (y1*s_PagedWidth);
for( y=0; y < (y2-y1); y++ )
{
#ifdef DOS
s_ScreenBlit( &pVgaMem[destBlitPos], &pScreenMem[srcBlitPos], blitSize );
#endif
destBlitPos += iWidthBytes;
srcBlitPos += s_PagedWidth;
}
}
// Right now this just swaps between page 0 and 1.
// Set our display page to the one we just drew on.
if( xPages > 1 )
{
if( curDispPage == 0 )
curDispPage = 1;
else
curDispPage = 0;
visStart = curDispPage * iWidthBytes * s_Height;
#ifdef DOS
outp( CRTC_ADDR, 0x0C );
outp( CRTC_ADDR+1, visStart >> 8 );
outp( CRTC_ADDR, 0x0D );
outp( CRTC_ADDR+1, visStart & 0xFF );
#endif
}
return TRUE;
}
BOOL s_Draw()
{
#ifdef DOS
DWORD plane;
DWORD actStart=0, visStart;
DWORD blitSize;
// Get our drawing page right.
if( xPages > 1 )
{
if( curDispPage == 0 )
actStart = 1 * iWidthBytes * s_Height;
else
actStart = 0;
}
blitSize = (s_SizeBytes/xPlanes)/4;
for( plane=0; plane < xPlanes; plane++ )
{
outpw( SEQ_ADDR, ( (0x01 << plane << 8)) + 0x02 );
s_ScreenBlit( &pVgaMem[actStart], &pScreenMem[plane * (s_SizeBytes/xPlanes)], blitSize );
}
// Right now this just swaps between page 0 and 1.
// Set our display page to the one we just drew on.
if( xPages > 1 )
{
if( curDispPage == 0 )
curDispPage = 1;
else
curDispPage = 0;
visStart = curDispPage * iWidthBytes * s_Height;
outp( CRTC_ADDR, 0x0C );
outp( CRTC_ADDR+1, visStart >> 8 );
outp( CRTC_ADDR, 0x0D );
outp( CRTC_ADDR+1, visStart & 0xFF );
}
#endif
return TRUE;
}
void sX_SetPixel( short x, short y, char color )
{
long actStart;
if( curDispPage == 0 )
actStart = 0;
else
actStart = 1 * iWidthBytes * s_Height;
outp( SEQ_ADDR, 0x02 );
outp( 0x3C5, 0x01 << (x & 3) );
pVgaMem[ (unsigned)(iWidthBytes * y) + (x / xPlanes) + actStart] = color;
}
// End of MODE X ifdef thing
#endif
#ifndef MODE_X
BOOL s_Init()
{
WORD x;
bScreenInitted = TRUE;
/* Set variables related to screen access */
s_Width = 320;
s_Height = 200;
s_SizeBytes = (long)s_Width * (long)s_Height;
/* Init stuff */
pVgaMem = (char *)VGA_MEM;
pScreenMem = new BYTE[s_SizeBytes];
// Create the x lookup information.
s_PagedWidth = s_Width;
s_PageLookup = new WORD[s_Width];
for( x=0; x < s_Width; x++ )
s_PageLookup[x] = x;
#ifdef DOS
oldScreenMode = s_GetMode();
/* Set VGA BIOS mode 13h: */
s_SetMode(0x13);
#endif
#ifdef PALETTE_MAPS
/* Load the palette maps and set the palette */
if( s_SetPaletteMaps() == FALSE )
return FALSE;
#ifdef DOS
s_SetPalette( palette );
#endif
#endif
return TRUE;
}
BOOL s_Draw()
{
#ifdef DOS
s_WaitForRetrace();
s_ScreenBlit( pVgaMem, pScreenMem, 16000 );
#endif
return TRUE;
}
#endif
BOOL s_UnInit( BOOL bDeleteMaps )
{
short i;
delete s_PageLookup;
if( bDeleteMaps )
{
// Get rid of the palette map.
for( i=0; i < nPaletteMaps; i++ )
delete pPaletteMaps[i];
delete pPaletteMaps;
}
#ifdef DOS
// Set the original screen mode.
s_SetMode( oldScreenMode );
#endif
free( pScreenMem );
return TRUE;
}
BOOL s_Clear( BYTE fillWith )
{
s_DWordMemSet( pScreenMem, fillWith, s_SizeBytes>>2 );
return TRUE;
}
BOOL s_ClearHalf( BYTE fillWith )
{
s_DWordMemSet( &pVgaMem[s_SizeBytes>>1], fillWith, (s_SizeBytes>>3) );
return TRUE;
}
void ResetVideoMode(WORD mode)
{
if( mode >= 0 && mode < 5 )
videoMode = mode;
delete s_PageLookup;
delete pScreenMem;
s_SetVideoMode( videoMode );
pScreenMem = new BYTE[s_SizeBytes];
#ifdef DOS
s_SetPalette( curLevel.palette );
#endif
// Reset the viewing parameters.
s_MinY = 0;
s_MaxY = s_Height;
s_MinX = 0;
s_MaxX = s_Width;
s_DrawWidth = s_Width;
s_DrawHeight = s_Height;
}
#ifdef DOS
void s_BlitChar(int xc,int yc,char c,int color,int trans_flag)
{
// this function uses the rom 8x8 character set to blit a character on the
// video screen, notice the trick used to extract bits out of each character
// byte that comprises a line
int offset,x,y;
char *work_char;
unsigned char bit_mask = 0x80;
// compute starting offset in rom character lookup table
work_char = rom_char_set + (0xFA6EL) + c * CHAR_HEIGHT;
// compute offset of character in video buffer
offset = (yc * s_PagedWidth);
for (y=0; y<CHAR_HEIGHT; y++)
{
// reset bit mask
bit_mask = 0x80;
for (x=0; x<CHAR_WIDTH; x++)
{
// test for transparent pixel i.e. 0, if not transparent then draw
if ((*work_char & bit_mask))
pScreenMem[offset + s_PageLookup[x + xc]] = color;
else if (!trans_flag) // takes care of transparency
pScreenMem[offset + s_PageLookup[x + xc]] = 0;
// shift bit mask
bit_mask = (bit_mask>>1);
}
// move to next line in video buffer and in rom character data area
offset += s_PagedWidth;
work_char++;
}
} // end Blit_Char
void s_BlitString(int x,int y,int color, char *string,int trans_flag)
{
// this function blits an entire string on the screen with fixed spacing
// between each character. it calls blit_char.
int index;
for (index=0; string[index]!=0; index++)
s_BlitChar(x+(index<<3),y,string[index],color,trans_flag);
} /* end Blit_String */
void s_SetMode( char modeNum )
{
union REGS regs;
regs.h.al = modeNum;
regs.h.ah = 0;
int386( 0x10, ®s, ®s );
}
char s_GetMode()
{
union REGS regs;
struct SREGS sregs;
segread( &sregs );
regs.h.ah = 0x0F;
int386x( 0x10, ®s, ®s, &sregs );
return regs.h.al;
}
BOOL s_SetPalette( char *palette )
{
int i;
/* Wait for retraces */
s_WaitForRetrace();
/* Dump the buffer to the card */
outp( 0x3C8, 0x0 );
for( i=0; i < 768; i++ )
outp( 0x3C9, palette[i] );
return TRUE;
}
BOOL s_Alert( char *message )
{
printf(message);
return TRUE;
}
void s_WaitForRetrace()
{
while( (inp(0x3DA) & 8) != 0 );
while( (inp(0x3DA) & 8) == 0 );
}
#else //(#ifdef DOS)
// Dummy version of functions so the same code will work..
void s_BlitChar(int xc,int yc,char c,int color,int trans_flag)
{
xc=xc;
yc=yc;
c=c;
color=color;
trans_flag=trans_flag;
}
void s_BlitString(int x,int y,int color, char *string,int trans_flag)
{
x=x;
y=y;
color=color;
string=string;
trans_flag=trans_flag;
}
#endif // End of an #ifdef DOS.
#pragma aux s_ScreenBlit = \
"START_COPY:" \
"lodsd" \
"stosd" \
"loopnz START_COPY" \
modify [eax] \
parm [edi] [esi] [cx];
#pragma aux s_DWordMemSet = \
"mov bl,al" \
"mov ah,al" \
"bswap eax" \
"mov al,bl" \
"mov ah,bl" \
"repnz stosd" \
modify [eax bl] \
parm [edi] [al] [ecx];
BOOL s_SetPixel( WORD x, WORD y, BYTE color )
{
long drawPos;
if( x < s_Width && x >= 0 && y < s_Height && y >= 0 )
{
drawPos = (y*s_PagedWidth) + s_PageLookup[x];
pScreenMem[drawPos] = color;
return TRUE;
}
return FALSE;
}
BOOL s_SetPaletteMaps()
{
FILE *fp;
short i, j, tempColor;
if( (fp = fopen(PALETTE_MAP, "r")) == NULL )
{
nPaletteColors=0;
nPaletteMaps=0;
pPaletteMaps = NULL;
return FALSE;
}
fscanf( fp, "%hd", &nPaletteColors );
fscanf( fp, "%hd", &nPaletteMaps );
// Read the palette in.
for( i=0; i < nPaletteColors; i++ )
{
fscanf( fp, "%hd", &tempColor );
palette[i*3] = (BYTE)tempColor;
fscanf( fp, "%hd", &tempColor );
palette[i*3+1] = (BYTE)tempColor;
fscanf( fp, "%hd", &tempColor );
palette[i*3+2] = (BYTE)tempColor;
}
// Set all the extra colors to black
for( i = nPaletteColors; i < 256; i++ )
palette[i*3] = palette[i*3+1] = palette[i*3+2] = 0;
// Read the alternate palettes in
pPaletteMaps = (char **)malloc( sizeof(char *) * nPaletteMaps );
for( i=0; i < nPaletteMaps; i++ )
{
pPaletteMaps[i] = (char *)malloc( sizeof(char) * 256 );
for( j=0; j < nPaletteColors; j++ )
fscanf( fp, "%hd", &pPaletteMaps[i][j] );
for( j=nPaletteColors; j < 256; j++ )
pPaletteMaps[i][j] = 0;
}
fclose(fp);
return TRUE;
}